package script;

import java.util.ArrayList;

import main.ErrorException;

import define.ErrorDefine;
import define.FunctionType;
import define.VariableType;

public abstract class VariableContainer 
{
	protected ArrayList<Variable> m_variableList;
	protected VariableContainer m_father;
	protected ArrayList<Variable> m_globalVariable;
	
	public VariableContainer(VariableContainer father, ArrayList<Variable> global)
	{
		m_father = father;
		if(m_father == null)
		{
			m_globalVariable = global;
		}
		m_variableList = null;
	}
	
	public void addVariable(Variable var)
	{
		if(m_variableList == null)
		{
			m_variableList = new ArrayList<>();
		}
		m_variableList.add(var);
	}
	
	public Variable getVariable(String name)
	{
		if(m_variableList != null)
		{
			for(Variable temp: m_variableList)
			{
				if(temp.getName() != null && temp.getName().compareTo(name) == 0)
				{
					return temp;
				}
			}
		}
		if(m_globalVariable != null)
		{
			for(Variable temp: m_globalVariable)
			{
				if(temp.getName() != null && temp.getName().compareTo(name) == 0)
				{
					return temp;
				}
			}
		}
		if(m_father == null)
		{
			return null;
		}
		return m_father.getVariable(name);
	}
	
	public StringBuffer getVariableValue(BaseExpress var) throws ErrorException
	{
		BaseExpress temp = var;
		VariableType vt = var.getType();
		if(vt == VariableType.E_VARIABLE_VT)
		{
			var = getVariable(((Variable)var).getName());
			if(var == null)
			{
				throw new ErrorException(ErrorDefine.E_NO_VARIABLE_ERROR, ((Variable)temp).getName(), temp.getStart());
			}
			if(var.getType() == VariableType.E_LIST_VT)
			{
				ArrayList<StringBuffer> list = ((Variable)var).getValueList();
				if(list.size() == 0)
				{
					throw new ErrorException(ErrorDefine.E_OUT_RANGE_ERROR, ((Variable)temp).getName() + "  0", temp.getStart());
				}
				return list.get(0);
			}
			else if(var.getType() == VariableType.E_MAP_VT)
			{
				throw new ErrorException(ErrorDefine.E_MAP_HAS_NO_KEY_ERROR, ((Variable)temp).getName(), temp.getStart());
			}
		}
		else if(vt == VariableType.E_LIST_ELEMENT_VT)
		{
			BaseExpress list = getVariable(((Variable)var).getName());
			if(list == null)
			{
				throw new ErrorException(ErrorDefine.E_NO_VARIABLE_ERROR, ((Variable)temp).getName(), temp.getStart());
			}
			if(((Variable)list).getType() != VariableType.E_LIST_VT)
			{
				throw new ErrorException(ErrorDefine.E_VARIABLE_NOT_LIST_ERROR, ((Variable)temp).getName(), temp.getStart());
			}
			ArrayList<StringBuffer> values = ((Variable)list).getValueList();
			int index = ((Variable)var).getListIndex();
			if(index < 0)
			{
				index = values.size() + index;
			}
			if(index < 0 || index >= values.size())
			{
				throw new ErrorException(ErrorDefine.E_OUT_RANGE_ERROR, ((Variable)temp).getName() + "  " + index, temp.getStart());
			}
			return values.get(index);
		}
		else if(vt == VariableType.E_MAP_ELEMENT_VT)
		{
			BaseExpress map = getVariable(((Variable)var).getName());
			if(map == null)
			{
				throw new ErrorException(ErrorDefine.E_NO_VARIABLE_ERROR, ((Variable)temp).getName(), temp.getStart());
			}
			return ((Variable)map).getValueByKey(((Variable)var).getMapKey());
		}
		return var.getValue();
	}
	
	public VariableContainer getFather()
	{
		return m_father;
	}
	
	public abstract FunctionType getFunctionType();
}
